using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;

using Zhaoxi.Zhihu.SharedKerel.Domain;
using Zhaoxi.Zhihu.SharedKerel.Repositoy;
using Zhaoxi.Zhihu.SharedKerel.Specification;

namespace Zhaoxi.Zhihu.Infrastructure.Repositories;

public class EfReadRepository<T>(AppDbContext dbContext) : IReadRepository<T> where T:class,IEntity<int>
{
    protected readonly DbSet<T> DbSet=dbContext.Set<T>();
    public IQueryable<T> GetQueryable()
    {
        return dbContext.Set<T>().AsQueryable();
    }

    public async Task<T?> GetByIdAsync<TKey>(TKey id, CancellationToken cancellationToken = default) where TKey : notnull
    {
       return await dbContext.Set<T>().FindAsync(new object[] { id }, cancellationToken);
    }

    public Task<List<T>> GetListAsync(Expression<Func<T, bool>> expression, CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }

    public Task<int> GetCountAsync(Expression<Func<T, bool>> expression, CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }

    public async Task<List<T>> GetListAsync(ISpecification<T>? specification=null, CancellationToken cancellationToken = default)
    {
        return await SpecificationEvaluator.GetQuery(DbSet,specification).ToListAsync(cancellationToken);
    }

    public async Task<T?> GetSingleOrDefaultAsync(ISpecification<T>? specification=null,
        CancellationToken cancellationToken = default)
    {
        return await SpecificationEvaluator.GetQuery(DbSet,specification).FirstOrDefaultAsync(cancellationToken);
    }

    public async Task<int> CountAsync(ISpecification<T>? specification=null, CancellationToken cancellationToken = default)
    {
        return await SpecificationEvaluator.GetQuery(DbSet,specification).CountAsync(cancellationToken);
    }

    public async Task<bool> AnyAsync(ISpecification<T>? specification=null,CancellationToken  cancellationToken = default)
    {
        return await SpecificationEvaluator.GetQuery(DbSet,specification).AnyAsync(cancellationToken);
    }
}